class Contest < ActiveRecord::Base
  require 'fileutils'
  include Configurator
  include FileMover
  
  # Това се използва от will_paginate,
  # за да знае по колко обекта да показва на страница.
  cattr_reader :per_page
  @@per_page = 10

  
  has_many :problems
  validates_presence_of :set_code
  validates_presence_of :name
  validates_presence_of :duration
  validates_presence_of :about
  validates_presence_of :start_time
  validates_presence_of :show_sources
  validates_numericality_of :duration,:show_sources
  validates_format_of :set_code,:with => /^[^$\s\\#\*\.]*$/
  validates_length_of :set_code, :in => 2..30
  validates_inclusion_of :duration , :in => 10..86400, :message => "not in the allowed interval(10..86400(=60 days))"
  validate_on_update :may_update_directory
  before_update :change_directory_if_necessary
  validate_on_create :correct_directory
  after_create :make_directory
  after_save :add_configuration 
  before_destroy :remove_directory
  self.primary_key = "contest_id"
  def end_time
    self.start_time + self.duration*60
  end 

  def make_directory
    path = directory
    FileUtils.mkdir path unless File.exists? path
  end
  def synchronize
    make_directory
    add_configuration
  end
  def directory
    unless self.set_code
     raise ArgumentError.new("Directory method called for a contest without a set_code")
    end
    config = load_config
    dir = File.join(config["base_dir"],"sets")
    File.join(dir,self.set_code)
  end
  private 
  def add_configuration  
    File.open(File.join(directory,"set-info.conf"),"w") do |setinfo|
      setinfo.puts "name=#{self.name}"
      setinfo.puts "start_time=#{self.start_time.strftime "%Y-%m-%d %H:%M:%S"}"
      setinfo.puts "duration=#{self.duration}"
      setinfo.puts "show_sources=#{self.show_sources}"
      setinfo.puts "about=#{self.about}"
    end 
  end
  
  def correct_directory
    if FileTest.exists? directory and Contest.find_by_set_code(self.set_code)
      self.errors.add("set_code",":the directory already exists #{directory}")
      false
    end
  end
  def remove_directory
    self.problems.each do |p|
      p.destroy
    end
    d = Dir.new directory
    d.each do |t|
      FileUtils.rm(File.join(d.path,t)) unless t=~ /^\..*/
    end
    FileUtils.rmdir d.path
  end
  def may_update_directory
     return false if !self.set_code
     c = Contest.find(:first, :conditions => {:set_code => self.set_code})
     if c && c.contest_id != self.contest_id
       self.errors.add("set_code",":the directory already exists #{directory}")
       false
     end
  end
  def change_directory_if_necessary
    c = Contest.find_by_contest_id(self.contest_id)
    return if c.set_code == self.set_code
    to = directory
    from = c.directory
    move_dir(from,to)
  end
  
end
